package entidades;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import org.jgraph.graph.DefaultEdge;
import org.jgrapht.alg.CycleDetector;
import org.jgrapht.graph.ListenableDirectedGraph;

public class Sistema extends Thread {

	public static ListenableDirectedGraph<Vertice, String> grafo = new ListenableDirectedGraph(
			DefaultEdge.class);
	public static CycleDetector<Vertice, String> detector = new CycleDetector<Vertice, String>(
			grafo);
	public static List<Recurso> recursos = new ArrayList<Recurso>();

	public static List<Processo> processos = new ArrayList<Processo>();

	private static Sistema instance;

	private int tempoVerificacao;

	public static Recurso buscarRecurso(int aintId) {
		return recursos.get(aintId);
	}

	@Override
	public void run() {
		super.run();
		System.out.println("Sistema!");
		while (true) {
			try {
				sleep(1000 * tempoVerificacao);
				verificarDeadLock();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

	public static Sistema getInstance() {
		if (instance == null) {
			instance = new Sistema();
		}
		return instance;
	}

	public static void verificarDeadLock() {
		if (processos.size() > 0){
			if (detector.detectCycles()) {
				// Se existem ciclos então existe deadlock
				Set<Vertice> s = detector.findCycles();
				for (Vertice vertice : s) {
					if (vertice instanceof Processo) {
						Processo p = (Processo) vertice;
						p.deadlock = true;
						p.setStatus("Deadlock!");
					}
				}
				for (int i = 0; i < processos.size(); i++) {

					if (!s.contains(processos.get(i))) {
						processos.get(i).deadlock = false;
						processos.get(i).setStatus("Não Deadlock!");
					}
				}
			}
		}
	}

	// ---------------------C�digo do grafo ------------------------
	public static void requisitarPosse(Processo aobjProcesso, Recurso recurso) {
		// se o recurso n�o tem processo, atribui o recurso ao solicitante
		// Aresta: Recurso -> Processo
		if (recurso.getProcesso() == null) {
			if (grafo.containsEdge(aobjProcesso, recurso)) {
				grafo.removeEdge(aobjProcesso, recurso);
			}
			grafo.addEdge(recurso, aobjProcesso);
		} else
			// Aresta: Processo -> Recurso
			grafo.addEdge(aobjProcesso, recurso);

	}

	public static void liberarPosse(Processo processo, Recurso recurso) {
		grafo.removeEdge(recurso, processo);
	}

	// ----------------------Fim dos m�todos do grafo----------------
	public int getTempoVerificacao() {
		return tempoVerificacao;
	}

	public void setTempoVerificacao(int tempoVerificacao) {
		this.tempoVerificacao = tempoVerificacao;
	}

}